package com.gitee.melin.bee.core.jdbc;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import org.springframework.lang.Nullable;

public class JdbcInvocationHandler implements InvocationHandler {

    private final Connection target;

    public JdbcInvocationHandler(Connection target) {
        this.target = target;
    }

    @Override
    @Nullable
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // Invocation on ConnectionProxy interface coming in...

        switch (method.getName()) {
            case "equals":
                // Only consider equal when proxies are identical.
                return (proxy == args[0]);
            case "hashCode":
                // Use hashCode of PersistenceManager proxy.
                return System.identityHashCode(proxy);
            case "close":
                // Handle close method: suppress, not valid.
                return null;
            case "isClosed":
                return false;
            case "getTargetConnection":
                // Handle getTargetConnection method: return underlying Connection.
                return this.target;
            case "unwrap":
                return (((Class<?>) args[0]).isInstance(proxy) ? proxy : this.target.unwrap((Class<?>) args[0]));
            case "isWrapperFor":
                return (((Class<?>) args[0]).isInstance(proxy) || this.target.isWrapperFor((Class<?>) args[0]));
        }

        // Invoke method on target Connection.
        try {
            return method.invoke(this.target, args);
        } catch (InvocationTargetException ex) {
            throw ex.getTargetException();
        }
    }
}
